package brian.android.mvc.activity;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

import brian.android.mvc.activity.config.ActivityConstant;
import brian.android.mvc.annotation.ViewIdNotExistsException;
import brian.android.mvc.bean.BeanFactory;
import android.os.Bundle;
import android.util.Log;

/**
 * @Activity 어노테이션을 이용해 Activity를 Method 단위로 생성하고자 할 때 사용 
 * */
public abstract class AbstractMethodActivity extends AbstractActivity {
	private Method activityMethod;
	
	@Override
	protected void initAfterViewSet(Bundle savedInstanceState) {
		super.initAfterViewSet(savedInstanceState);
		invokeActivityMethod(savedInstanceState);
	}
	
	private void invokeActivityMethod(Bundle savedInstanceState) {
		if (activityMethod != null) {
			List<Object> arguments = BeanFactory.getArguments(activityMethod, this, savedInstanceState, Bundle.class);
			try {
				activityMethod.invoke(this, arguments.toArray());
			} catch (IllegalArgumentException e) {
				//TODO 여기서 Exception Wrapping
				Log.e(this.getClass().getSimpleName(), e.getMessage(), e);
			} catch (IllegalAccessException e) {
				Log.e(this.getClass().getSimpleName(), e.getMessage(), e);
				//TODO 버리는 Runtime Exception
			} catch (InvocationTargetException e) {
				Log.e(this.getClass().getSimpleName(), e.getMessage(), e);
				//TODO 버리는 Runtime Exception
			}
		}
	}

	/**
	 * contentView id를 intent param, getContentViewId(), ClassName 동일 method 순으로 찾는다. 
	 * @throws ViewIdNotExistsException view ID가 없을 경우 예외 
	 * */
	@Override
	protected int getContentView() throws ViewIdNotExistsException {
		int viewId = findViewidFromIntent();
		if (viewId <= 0) {
			viewId = findViewidFromClassName();
		}
		
		if (viewId <= 0) {
			throw new ViewIdNotExistsException("view id not exists in \"" + this.getClass().getSimpleName() + "\". 1. pass ACTIVITY_METHOD_NAME param using intent. 2. override getContentViewId() method. 3. declare annotation @Activity(layout=YourActivityClass)");
		}
		return viewId;
	}
	
	private String getActivityMethodNameFromIntent() {
		return getExtraValue(ActivityConstant.ACTIVITY_METHOD_NAME);
	}
	
	private int findViewidFromIntent() {
		String activityMethodName = getActivityMethodNameFromIntent();
		if (activityMethodName == null) {
			return -1;
		}
		return findViewidFromMethodName(activityMethodName);
	}

	private int findViewidFromClassName() {
		String className = this.getClass().getSimpleName();
		String methodName = className.substring(0, 1).toLowerCase() + className.substring(1);
		return findViewidFromMethodName(methodName);
	}

	private int findViewidFromMethodName(String methodName) {
		Method method = findMethodByName(methodName);
		brian.android.mvc.annotation.Activity activityAnnotation = method.getAnnotation(brian.android.mvc.annotation.Activity.class);
		if (activityAnnotation != null) {
			//FIXME Activity 의  Method를 여기서 설정한다. 위치가 좀 애매하다. 
			activityMethod = method;
			return activityAnnotation.layout();
		}
		return -1;
	}
	
	private Method findMethodByName(String activityMethodName) {
		for (Method method : this.getClass().getMethods()) {
			if (activityMethodName.equals(method.getName())) {
				return method;
			}
		}
		return null;
	}
}
